package cn.walls1717.juc.future;

import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 比价需求
 *
 * @author walls1717
 * @create 2022/12/09 14:18
 **/
@Slf4j
public class CompletableFutureMallDemo {
    private static final List<NetMall> netMalls =
        Arrays.asList(new NetMall("jd"), new NetMall("dd"), new NetMall("tb"));

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        // List<String> mysql = listPrice(netMalls, "mysql");
        List<String> mysql = listPriceByCompletableFuture(netMalls, "mysql");
        for (String s : mysql) {
            log.info(s);
        }
        long end = System.currentTimeMillis();
        log.info("业务耗时 -> {}", end - start);

    }

    /**
     * 串行执行
     *
     * @param netMalls
     * @param productName
     * @return
     */
    private static List<String> listPrice(List<NetMall> netMalls, String productName) {
        return netMalls.stream().map(netMall -> String.format(productName + " in %s price is %.2f",
            netMall.getMallName(), netMall.calcPrice(productName))).collect(Collectors.toList());
    }

    /**
     * 并行执行
     *
     * @param netMalls
     * @param productName
     * @return
     */
    private static List<String> listPriceByCompletableFuture(List<NetMall> netMalls, String productName) {
        return netMalls.stream()
            .map(netMall ->
                    CompletableFuture.supplyAsync(
                            () -> String.format(productName + " in %s price is %.2f",netMall.getMallName(), netMall.calcPrice(productName))
                    )
            )
            .collect(Collectors.toList())
            .stream()
            .map(CompletableFuture::join).collect(Collectors.toList());
    }

}

class NetMall {

    @Getter
    private final String mallName;

    public NetMall(String mallName) {
        this.mallName = mallName;
    }

    public double calcPrice(String productName) {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return ThreadLocalRandom.current().nextDouble() * 2 + productName.charAt(0);
    }
}
